﻿using System.Drawing;
using System.Windows.Forms;
using FBEntities.FBObjects.User;
using XDAFacebook;
using XFControls.Utils;
using FBEntities.FBObjects;
using System.Collections.Generic;

namespace XFControls.XFPanels.XFPanelItems
{
    internal class XFItemDisplayInfo : XFItemBase
    {
        private int _categoryHeight = 30;
        private int _height;
        private int _indent = 15;
        private Size _mesTitle;
        private int _singleLineText = 30;

        private List<CategoryText> _info;
        private Dictionary<string, Rectangle> _recs;

        public XFItemDisplayInfo(List<CategoryText> info)
        {
            _height = -1;
            _mesTitle = new Size(-1, -1);

            Style = new XFItemStyle
                        {
                            BackgroundColor = Color.White,
                            TextFont = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Regular),
                            TextColor = Color.DarkSlateGray,
                            Padding = 10
                        };

            if (XFGraphics.GetScreenResolutionNotRotated() == ScreenResolution.QVGA)
            {
                _categoryHeight /= 2;
                _singleLineText /= 2;
                _indent /= 2;
            }

            _info = info;
            _recs = new Dictionary<string, Rectangle>();
            ItemType = XFItemType.Display;
        }

        public override int GetHeight()
        {
            if (_height > 0)
                return _height;

            int width = Screen.PrimaryScreen.WorkingArea.Width;
            int curY = Style.PaddingTop;

            determinLongest();

            foreach (var categoryText in _info)
            {
                curY = getCategoryHeight(curY);
                foreach (var displayString in categoryText.Values)
                {
                    switch (displayString.Value.Type)
                    {
                        case DisplayStringType.Line:
                            curY = getLineTextHeight(curY);
                            break;
                        case DisplayStringType.Paragraph:
                            var rec = new Rectangle();
                            curY = getParagraphTextHeight(width, displayString.Value.Display, curY, ref rec);
                            _recs.Add(categoryText.Category + "." + displayString.Key, rec);
                            break;
                    }
                }
            }

            _height = curY;

            return _height;
        }

        public override void ResetHeight()
        {
            _height = -1;
        }

        public override void ItemPaint(Graphics gf, int x, int y)
        {
            base.ItemPaint(gf, x, y);
            int width = GetWidth();
            int xLocal = 0;

            int curY = 0;
            using (var pCat = new Pen(Color.MidnightBlue))
            using (var bCat = new SolidBrush(Color.LightSteelBlue))
            using (var fCat = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Regular))
            using (var bText = new SolidBrush(Color.Black))
            {
                foreach (var categoryText in _info)
                {
                    curY = drawCategory(gf, width, categoryText.Category, pCat, bCat, bText, fCat, xLocal, curY);
                    foreach (var displayString in categoryText.Values)
                    {
                        switch (displayString.Value.Type)
                        {
                            case DisplayStringType.Line:
                                curY = drawLineText(gf, width, displayString.Key + ":  " + displayString.Value, bText, curY);
                                break;
                            case DisplayStringType.Paragraph:
                                var rec = _recs[categoryText.Category + "." + displayString.Key];
                                drawParagraphText(gf, displayString.Key, displayString.Value.Display, bText, rec);
                                break;
                        }
                    }
                }
            }
        }

        private void determinLongest()
        {
            if (_mesTitle.Width > 0)
                return;

            string cur;
            Size curMes;

            foreach (var categoryText in _info)
            {
                foreach (var displayString in categoryText.Values)
                {
                    if(displayString.Value.Type == DisplayStringType.Line) continue;

                    cur = displayString.Value.Display;
                    curMes = Style.TextFont.MeasureString(cur, new Rectangle(0, 0, 400, 0));
                    if (_mesTitle.Width < curMes.Width)
                        _mesTitle = curMes;
                }
            }

            _mesTitle.Width += _indent;
        }

        private int drawLineText(Graphics g, int width, string text, SolidBrush bText, int curY)
        {
            if (Style == null) return curY + _singleLineText;
            g.DrawString(XFControlUtils.EllipsisWord(width - (_indent * 2), text, Style.TextFont), Style.TextFont, bText,
                         _indent, curY);
            return curY + _singleLineText;
        }

        private int getLineTextHeight(int curY)
        {
            return curY + _singleLineText;
        }

        private void drawParagraphText(Graphics g, string text, string title, SolidBrush bText, Rectangle rec)
        {
            title = title + ":  ";
            if (rec.Y <= 0) return;

            g.DrawString(title, Style.TextFont, bText, _indent, rec.Y);
            g.DrawString(text, rec, Style, bText.Color);
        }

        private int getParagraphTextHeight(int width, string text, int curY, ref Rectangle output)
        {
            int titleWidth = _mesTitle.Width;
            output = new Rectangle(_indent + titleWidth, curY, width - (_indent * 2) - titleWidth, 0);

            if (string.IsNullOrEmpty(text))
                return curY + _singleLineText;

            int recHeight = Style.TextFont.MeasureString(text, output).Height;
            output.Height = recHeight;

            return curY + recHeight + Style.PaddingTop;
        }

        private int drawCategory(Graphics g, int width, string title, Pen pCat, SolidBrush bCat, SolidBrush bText,
                                 Font fCat, int x, int curY)
        {
            int ret = curY + _categoryHeight + Style.PaddingTop;

            g.FillRectangle(bCat, x, curY, width, _categoryHeight);
            g.DrawLine(pCat, x, curY, width, curY);

            g.DrawString(title, fCat, bText, x + Style.PaddingLeft, curY + 3);

            return ret;
        }

        private int getCategoryHeight(int curY)
        {
            return curY + _categoryHeight + (Style.PaddingLeft + Style.PaddingRight);
        }
    }

    public class CategoryText
    {
        public string Category;
        public Dictionary<string, DisplayString> Values = new Dictionary<string, DisplayString>();
    }

    public class DisplayString
    {
        public DisplayStringType Type;
        public string Display;
    }
    public enum DisplayStringType
    {
        Line,
        Paragraph
    }
}